/*
* 实现一个队列结构，符合FIFO（先进先出）的原则，仓库数据里面，在尾部添加新元素，在顶部移除元素，最新添加的元素必须排在队列的末尾。
*   enqueue：向队列尾部添加一个或是多个新的项，类似push
*   dequeue：移除队列的第一项，就是当前队列最前面的那个，并返回删除的元素，类似于shift
*   peek：返回队列的第一项，当前队列中最早添加的也是会最先被删除的那一项
*   isEmpty：判断是否为空
*   size：队列的数据个数
*   clear：清空队列
*   toString：转字符串
*   迭代器
*
* */

class Queue{
    constructor(){
        this.count = 0 //计数器
        this.items = {} //队列的数据仓库
    }
    enqueue(...eles){ //在队列尾部增加一项
        for(let i = 0, len = eles.length; i < len; i++){
            this.items[this.count] = eles[i] //采用计数器当前值（自然数）为下标key，存储实际数据
            this.count++ //每次push进一个数据，计数器自增1
        }
    }
    isEmpty(){
        return !this.count
    }
    dequeue(){ //移除队列当前最前面一项
        if(this.isEmpty()){
            return undefined
        }else{
            let result = this.items[0] //先将队列最前面的那一项保存下来，因为移除了最前面一项，队列后面剩下的所有项都会相应地往前挪一位
            for(let i = 0; i < this.count - 1; i++){
                this.items[i] = this.items[i + 1] //循环将剩下队列的每一项向前挪一位，就是将后一项值赋值给前一项
            }
            delete this.items[this.count - 1] //当剩下所有的项都往前挪了一位，最后一位会赋值给倒数第二位，这样就有两个是相同的，所以删除最后一位
            this.count-- //每次删除一位，相应的计数器要自减1
            return result //返回我们一开始保存好的队列要删除的第一位
        }
    }
    peek(){ //先进先出，返回队列里最早添加的也是会最先被删除的那一项
        if(this.isEmpty()){
            return undefined
        }else{
            return this.items[0]
        }
    }
    size(){
        return this.count
    }
    toString(){
        if(this.isEmpty()){
            return ""
        }else{
            let objString = ""
            for(let i = 0; i < this.count; i++){
                objString = `${objString},${this.items[i]}`
            }
            return objString.slice(1)
        }
    }
    [Symbol.iterator](){ //手动添加一个迭代器接口
        let self = this //先保存好当前的this
        let index = 0 //定义一个索引
        return {
            next(){
                if(index < self.count){ //如果没有遍历结束，则一个个返回当前值
                    return {
                        value:self.items[index++], //运用了闭包
                        done:false //false表示没有遍历完成
                    }
                }else{ //否则如果变量结束，则返回undefined
                    return {
                        value:undefined,
                        done:true //true表示遍历结束
                    }
                }
            }
        }
    }
}

let queue = new Queue()